package nccloud.utils.riart;

import com.sm.misc.BASE64Encoder;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.server.ISecurityTokenCallback;
import nc.bs.logging.Logger;
import nc.itf.uap.IUAPQueryBS;
import nc.itf.uap.busibean.ISysInitQry;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.data.ValueUtils;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

/**
 * 同步代办消息给第三方(致远OA)工具类
 *
 * @author shixh
 * @date 2022年4月25日
 */
public class MsgSyncUtils {

    /**
     * 获取配置的代办消息固定参数[自定义档案]
     */
    public static String PARAM = "SMG_TYPE";
    /**
     * 接口类型编码，方便后续做报表[自定义档案]
     */
    public static String JKRZ = "JKRZ";
    /**
     * NCC是否同步代办消息[参数]
     */
    public static String PF005 = "PF005";
    /**
     * 消息集成打开NCC单据对应的服务器IP[参数]
     */
    public static String IP = "IP";
    /**
     * OA系统消息代办接口地址[参数]
     */
    public static String FWURL = "FWURL";
    /**
     * 第三方系统创建代办+通知消息的标识
     */
    public static String CREATEMSG = "CREATEMSG";
    /**
     * 第三方系统创建代办的标识
     */
    public static String CREATEDB = "CREATEDB";
    /**
     * 第三方系统创建通知消息的标识
     */
    public static String CREATENOTICE = "CREATENOTICE";
    /**
     * 第三方系统标记待办事件为已处理的标识
     */
    public static String UPDATEMSG = "UPDATEMSG";
    /**
     * 第三方系统删除代办的标识
     */
    public static String DELETEMSG = "DELETEMSG";
    /**
     * 异构系统标识
     */
    public static String SYSCODE = "NCC";
    /**
     * // PC端URL
     */
    public static String OAPCURRL = "OAPCURRL";
    /**
     * // app端URL
     */
    public static String OAAPPURL = "OAAPPURL";


    /**
     * OA消息接口-REST账号【测试】
     */
    public static String ACCOUNT = "RestForNCC";
    /**
     * OA消息接口-REST密码【测试】
     */
    public static String PASSWORD = "c48b2db9-d233-4fc8-b24c-1d5d065e5960";
    /**
     * OA消息接口-消息待办应用编码【测试】
     */
    public static String OACODE = "3001";

    /**
     * 获取OA系统token
     *
     * @return
     */
    public static String getOAtoken() {
        String TokenUrl = "/seeyon/rest/token/" + ACCOUNT + "/" + PASSWORD;
        String token = HttpRequestUtils.doGet(MsgSyncUtils.queryGroupSysParam(MsgSyncUtils.FWURL) + TokenUrl);
        MessageLogger.info("获取的OAtoken：" + token);
        return token;

    }

    /**
     * 判断NCC是否启用代办消息同步
     *
     * @return
     * @throws BusinessException
     */
    public static boolean NCISSync() throws BusinessException {
        ISysInitQry sysInitQry = NCLocator.getInstance().lookup(ISysInitQry.class);
        String ISSYBIP = sysInitQry.getParaString("GLOBLE00000000000000", MsgSyncUtils.PF005);// 根据参数代码和集团获取参数值
        if (ISSYBIP != null && "Y".equals(ISSYBIP)) {
            return true;
        }
        return false;
    }

    /**
     * 查询集团参数
     *
     * @param code
     * @return
     */
    public static String queryGroupSysParam(String code) {
        String initData = null;
        try {
            ISysInitQry sysInitQry = NCLocator.getInstance().lookup(ISysInitQry.class);
            initData = sysInitQry.getParaString("GLOBLE00000000000000", code);// 根据参数代码和集团获取参数值
        } catch (BusinessException e) {
            MessageLogger.error("根据代码获取集团参数【" + code + "】异常：" + e.getMessage());
            ExceptionUtils.wrappBusinessException("根据代码获取集团参数【" + code + "】异常：" + e.getMessage());
        } catch (Exception e) {
            MessageLogger.error("根据代码获取集团参数【" + code + "】异常：" + e.getMessage());
        }
        return initData;
    }

    /**
     * 根据组织判断是否消息同步
     *
     * @param pk_org
     * @return
     * @throws BusinessException
     */
    public static boolean ISSyncMsgByOrg(String pk_org) throws BusinessException {
        StringBuffer sb = new StringBuffer();
        sb.append("	select def1 from org_orgs  where pk_org = '" + pk_org + "'	");
        IUAPQueryBS query = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        String value = (String) query.executeQuery(sb.toString(), new ColumnProcessor());
        if (value != null && ("Y".equals(value) || "true".equals(value))) {
            return true;
        }
        return false;
    }

    /**
     * 获取单据对应的模块编码[自定义档案]SMG_TYPE
     *
     * @param billtype
     * @return
     * @throws BusinessException
     */
    public static String getModuleCode(String billtype) throws BusinessException {
        StringBuffer sb = new StringBuffer();
        sb.append("	select memo	");
        sb.append("	 from bd_defdoc	");
        sb.append("	 where dr = 0	");
        sb.append("	 and enablestate   = 2	");
        sb.append("	 and pk_defdoclist = (select pk_defdoclist	");
        sb.append("	 from bd_defdoclist	");
        sb.append("	 where code = '" + MsgSyncUtils.PARAM + "' ");
        sb.append("	 and dr= 0)	");
        sb.append("	 and code = '" + billtype + "'	");
        IUAPQueryBS query = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        String value = (String) query.executeQuery(sb.toString(), new ColumnProcessor());
        if (value == null) {
            value = "";
        }
        return value;
    }

    /**
     * 获取支持的交易类型[自定义档案]SMG_TYPE
     *
     * @param billtype
     * @return
     * @throws BusinessException
     */
    public static boolean getTransType(String billtype) throws BusinessException {
        StringBuffer sb = new StringBuffer();
        sb.append("	select code	");
        sb.append("	 from bd_defdoc	");
        sb.append("	 where dr = 0	");
        sb.append("	 and enablestate   = 2	");
        sb.append("	 and pk_defdoclist = (select pk_defdoclist	");
        sb.append("	 from bd_defdoclist	");
        sb.append("	 where code = '" + MsgSyncUtils.PARAM + "' ");
        sb.append("	 and dr = 0)	");
        sb.append("	 and code = '" + billtype + "'	");
        IUAPQueryBS query = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        String value = (String) query.executeQuery(sb.toString(), new ColumnProcessor());
        if (value != null) {
            return true;
        }
        return false;
    }

    /**
     * 获取接口日志类型[自定义档案]JKRZ
     *
     * @param billtypecode
     * @return
     * @throws BusinessException
     */
    public static String getJKRZCode(String billtypecode) {
        String value = "";
        StringBuffer sb = new StringBuffer();
        try {
            sb.append("	select name	");
            sb.append("	 from bd_defdoc	");
            sb.append("	 where dr = 0	");
            sb.append("	 and enablestate   = 2	");
            sb.append("	 and pk_defdoclist = (select pk_defdoclist	");
            sb.append("	 from bd_defdoclist	");
            sb.append("	 where code = '" + MsgSyncUtils.JKRZ + "' ");
            sb.append("	 and dr = 0)	");
            sb.append("	 and code = '" + billtypecode + "'	");
            IUAPQueryBS query = NCLocator.getInstance().lookup(IUAPQueryBS.class);
            value = ValueUtils.getString(query.executeQuery(sb.toString(), new ColumnProcessor()));
            if (value == null) {
                value = "";
            }
        } catch (Exception e) {
            MessageLogger.error("查询接口日志类型[自定义档案]异常：" + sb.toString());
            ExceptionUtils.wrappBusinessException("查询接口日志类型[自定义档案]异常：" + sb.toString());
        }
        return value;
    }

    /**
     * @param sql
     * @return
     * @throws Exception
     * @throws BusinessException
     */
    @SuppressWarnings("unchecked")
    public static Map<Object, Object> executeQuery(String sql) {
        IUAPQueryBS query = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        Map<Object, Object> map = null;
        try {
            map = (Map<Object, Object>) query.executeQuery(sql, new MapProcessor());
        } catch (BusinessException e) {
            MessageLogger.error("查询异常sql：" + sql + ",异常信息" + e.getMessage());
            ExceptionUtils.wrappBusinessException("查询异常sql：" + sql + ",异常信息" + e.getMessage());
        } catch (Exception e) {
            MessageLogger.error("查询异常sql：" + sql + ",异常信息" + e.getMessage());
            ExceptionUtils.wrappBusinessException("查询异常sql：" + sql + ",异常信息" + e.getMessage());
        }
        return map;
    }

    /**
     * @param sql
     * @return
     * @throws Exception
     * @throws BusinessException
     */
    @SuppressWarnings("unchecked")
    public static List<Map<String, Object>> executeQueryList(String sql) {
        IUAPQueryBS query = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        List<Map<String, Object>> list = null;
        try {
            list = (List<Map<String, Object>>) query.executeQuery(sql, new MapListProcessor());
        } catch (BusinessException e) {
            ExceptionUtils.wrappBusinessException("查询异常sql：" + sql + ",异常信息" + e.getMessage());
        } catch (Exception e) {
            MessageLogger.error("查询异常sql：" + sql + ",异常信息" + e.getMessage());
            ExceptionUtils.wrappBusinessException("查询异常sql：" + sql + ",异常信息" + e.getMessage());
        }
        return list;
    }

    /**
     * 按参数名排序后依次拼接参数名称与数值，之后对该字符串使用 HmacSHA256 加签，加签结果进行 base 64 返回
     *
     * @param params      请求参数 map
     * @param suiteSecret 套件密钥，用作 mac key
     * @return 签名
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     */
    public static String sign(Map<String, String> params, String suiteSecret)
            throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        Map<String, String> treeMap;
        if (params instanceof TreeMap) {
            treeMap = params;
        } else {
            treeMap = new TreeMap<>(params);
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : treeMap.entrySet()) {
            stringBuilder.append(entry.getKey()).append(entry.getValue());
        }
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(suiteSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        String base64String = new BASE64Encoder().encode(signData);
        return URLEncoder.encode(base64String, "UTF-8");
    }

    /*
     * 读取参数配置文件
     *
     * @return Properties
     */
    public static Properties getProperties() {
        Properties p = new Properties();
        FileInputStream in = null;
        try {
            in = new FileInputStream(
                    new File(MsgSyncUtils.class.getResource(".").getPath().toString() + "sms.properties"));
            p.load(in);
        } catch (FileNotFoundException e) {
            ExceptionUtils.wrappBusinessException("写入参数信息失败！");
            Logger.error("找不到参数配置文件！");
        } catch (IOException e) {
            ExceptionUtils.wrappBusinessException("写入参数信息失败！");
            Logger.error("写入参数信息失败！");
            e.printStackTrace();
        }
        return p;
    }

    /**
     * 模拟登陆
     */
    public static void setDataSource() {
        // 指定数据源为ncc
        String autoStock = MsgSyncUtils.getProperties().getProperty("sms.MESTNC");
        if (autoStock == null || "".equals(autoStock)) {
            autoStock = "ncctest1123";
        }
        InvocationInfoProxy.getInstance().setUserDataSource(autoStock);
        ISecurityTokenCallback sc = (ISecurityTokenCallback) NCLocator.getInstance()
                .lookup(ISecurityTokenCallback.class);
        sc.token("NCSystem".getBytes(), "pfxx".getBytes());
        Logger.error("指定数据源为" + autoStock);
    }
}
